#include "vtor_shell.h"
#include "vtor_string.h"
#include "vtor_timer.h"

#ifdef __VTOR_SHELL__

VtorShell* vtorShellHeader = NULL;

void VtorShell_Void(void)
{
}

void VtorShell_Help(void)
{
	VtorShell_PrintString("\tVtorShell_Help(void)\r\n");
	VtorShell_PrintString("\tVtorShell designed by vtor3478@qq.com\r\n");
	VtorShell_PrintString("\tcurrent date 2024-09-13\r\n\r\n");
	
	VtorShell_PrintString("\texample:\r\n");
	VtorShell_PrintString("\t\tlist\r\n");
	VtorShell_PrintString("\t\tint(20)\r\n");
	VtorShell_PrintString("\t\tint(0x24)\r\n");
	VtorShell_PrintString("\t\tstr(\"123abc\")\r\n");
}

void VtorShell_List(void)
{
	VtorShell* shell = vtorShellHeader;
	if(NULL == shell)
	{
		return;
	}
	while(NULL != shell->fun)
	{
		uint8_t shellListBuf[50] = {0};
		VtorString_Clear(shellListBuf);
		VtorString_AppendString(shellListBuf, "\t");
		VtorString_AppendString(shellListBuf, shell->name);
		VtorString_AppendString(shellListBuf, "\r\n");
		VtorShell_PrintString(shellListBuf);
		shell++;
	}
}

int32_t VtorShell_Int(int32_t num)
{
	uint8_t buf[50] = { 0 };
	VtorString_Clear(buf);
	VtorString_AppendString(buf, "\tVtorShell_Int(");
	VtorString_AppendInt(buf, num);
	VtorString_AppendString(buf, ") = hex(");
	VtorString_AppendHex(buf, num);
	VtorString_AppendString(buf, ")\r\n");
	VtorShell_PrintString(buf);
	return num;
}

int32_t VtorShell_String(uint8_t* str)
{
	uint8_t buf[50] = { 0 };
	VtorString_Clear(buf);
	VtorString_AppendString(buf, "\tVtorShell_String(\"");
	VtorString_AppendString(buf, str);
	VtorString_AppendString(buf, "\")\r\n");
	VtorShell_PrintString(buf);
	return 0;
}

int32_t VtorShell_Call(uint32_t addr)
{
	return 0;
}

void VtorShell_WriteMem(int32_t addr, int32_t val)
{
	*(int32_t*)addr = val;
}

int32_t VtorShell_ReadMem(int32_t addr)
{
	return *(int32_t*)addr;
}


#ifdef __VTOR_SHELL_CONFIG_GET_TIME_RESERVE__
int32_t VtorShell_GetTime()
{
#ifdef __VTOR_TIMER__
	return VtorTimer_GetTick();
#else
	return 0;
#endif
}
#endif // __VTOR_SHELL_CONFIG_GET_TIME_RESERVE__


VtorShell* VtorShell_GetShell(uint8_t* str)
{
	int16_t mostSimilarity = 0;
	VtorShell* shell = vtorShellHeader;
	VtorShell* mostSimilarityShell = NULL;
	if(NULL == shell)
	{
		return NULL;
	}
	while(shell->fun)
	{
		int16_t similarity = VtorString_GetSimilarity(str, shell->name);
		if(similarity > 50 // 有足够的相似度
			&& similarity > mostSimilarity) // 并且比历史最高更高
		{
			// 记录最大相似度的shell
			mostSimilarityShell = shell;
			mostSimilarity = similarity;
		}
		shell++;
	}
	// 返回相似度最高的shell
	return mostSimilarityShell;
}

int32_t VtorShell_GetArg(uint8_t* str, int32_t* argv, int8_t* argt)
{
	//char* splitArray = {" (),"};
	int8_t argc = 0;

	uint8_t* argStr = VtorString_FindString(str, "(");
	while(*argStr)
	{
		argStr = VtorString_GetNextValueType(argStr, argt);
		if(VtorVar_Int == *argt || VtorVar_Hex == *argt)
		{
			argStr = VtorString_FindInt(argStr, argv);
		}
		else if(VtorVar_String == *argt)
		{
			argStr = VtorString_CutString(argStr, argv);
		}
		if (*argStr)
		{
			argv++;
			argc++;
			argt++;
		}
	}
	return argc;
}

void VtorShell_PrintArg(VtorShell* shell, uint8_t argc, int32_t* argv, int8_t* argt)
{
	uint8_t i = 0;
	uint8_t infoBuf[127] = {0};
	uint8_t* infoStr = infoBuf;
	infoStr = VtorString_AppendString(infoStr, shell->name);
	infoStr = VtorString_AppendString(infoStr, " (");
	for(i = 0; i < argc; i++)
	{
		if(VtorVar_Int == argt[i])
		{
			infoStr = VtorString_AppendInt(infoStr, argv[i]);
		}
		else if(VtorVar_Hex == argt[i])
		{
			infoStr = VtorString_AppendHex(infoStr, argv[i]);
		}
		else if(VtorVar_String == argt[i])
		{
			infoStr = VtorString_AppendString(infoStr, "\"");
			infoStr = VtorString_AppendString(infoStr, (uint8_t*)(argv[i]));
			infoStr = VtorString_AppendString(infoStr, "\"");
		}
		if(i == argc - 1)
		{
			break;
		}
		infoStr = VtorString_AppendString(infoStr, ", ");
	}
	infoStr = VtorString_AppendString(infoStr, ")\r\n{\r\n");
	VtorShell_PrintString(infoBuf);
}

void VtorShell_PrintRet(int32_t retVal, int32_t execTick)
{
	uint8_t retBuf[127] = {0};
	uint8_t* retStr = retBuf;
	retStr = VtorString_AppendString(retStr, "\treturn ");
	retStr = VtorString_AppendInt(retStr, retVal);
	retStr = VtorString_AppendString(retStr, "(");
	retStr = VtorString_AppendHex(retStr, retVal);
	retStr = VtorString_AppendString(retStr, "); // elapsed ");
	retStr = VtorString_AppendInt(retStr, execTick);
	retStr = VtorString_AppendString(retStr, " tick\r\n}\r\n\r\n");
	VtorShell_PrintString(retBuf);
}

#ifdef __VTOR_SHELL_CONFIG_MINI__

int32_t VtorShell_Scan(uint8_t* str)
{
	VtorShell* shell = VtorShell_GetShell(str);
	if(shell)
	{
		shell->fun();
	}
	return 0;
}

#else // __VTOR_SHELL_CONFIG_MINI__

int32_t VtorShell_Scan(uint8_t* userStr)
{
	uint8_t str[256] = {0};
	memcpy(str, userStr, 255); // 保留最后一个字符作为结束符
	VtorString_Preprocess(str); // 允许用户使用注释且不影响使用
	VtorShell* shell = VtorShell_GetShell(str);
	if(shell)
	{
		int32_t argValueBuf[10] = { 0 }; // 使用int32_t存储数值
		int8_t argTypeBuf[10] = { 0 }; // 使用int32_t存储另外类型
		
		int32_t* argv = argValueBuf;
		int8_t* argt = argTypeBuf;

		int8_t argc = VtorShell_GetArg(str, argv, argt);
		VtorShell_PrintArg(shell, argc, argv, argt);
		if(VtorString_GetSimilarity(shell->name, "call") > 50) // 如果是函数地址调用
		{
			// 如果是函数调用，那么移动参数指针，调整参数个数
			shell->fun = (VtorShellFun)argv[0];
			argc--;
			argv++;
		}
		uint32_t execTick = VtorShell_GetTime();

		int32_t retVal = VtorShell_Exec(shell, argc, argv);

		execTick = VtorShell_GetTime() - execTick;
		VtorShell_PrintRet(retVal, execTick);
		return retVal;
	}
	return 0;
}

#endif // __VTOR_SHELL_CONFIG_MINI__

int32_t VtorShell_Exec(VtorShell* shell, uint8_t argc, int32_t* argv)
{
	int32_t ret = 0;
	switch (argc)
	{
	case 0:
		ret = shell->fun();
		break;
	case 1:
		ret = shell->fun(argv[0]);
		break;
	case 2:
		ret = shell->fun(argv[0], argv[1]);
		break;
	case 3:
		ret = shell->fun(argv[0], argv[1], argv[2]);
		break;
	case 4:
		ret = shell->fun(argv[0], argv[1], argv[2], argv[3]);
		break;
	case 5:
		ret = shell->fun(argv[0], argv[1], argv[2], argv[3], argv[4]);
		break;
	case 6:
		ret = shell->fun(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
		break;
	case 7:
		ret = shell->fun(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
		break;
	case 8:
		ret = shell->fun(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
		break;
	case 9:
		ret = shell->fun(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
		break;
	case 10:
		ret = shell->fun(argv[0], argv[1], argv[2], argv[2], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9]);
		break;
	default:
		break;
	}
	return ret;
}







#endif // __VTOR_SHELL__

